#include "Deck.h"
#include "Card.h"
#include "Random.h"
#include <cassert>

using namespace std;

Deck::Deck(int cards, int decks)
    :deck(cards * decks)
{
    assert(cards > 0);
    assert(decks > 0);
    //	create an ordered deck
    for (int i = 0; i < decks; ++i)
    {
        int j;
        for(j = 0; j < 52; ++j)
            deck[i * cards + j] = (char)(j + 1);

        for(j = 52; j < cards; ++j)
            deck[i * cards + j] = (char)Card::JOKER;
    }
}

Deck::~Deck()
{
}
	
void Deck::shuffle(Random& ran)
{
    // shuffle from first card to end card in the deck
    shufflePartial(0, deck.size() - 1, ran);
}

//shuffle the deck starting at a particular card
//  -- start, >= 0, 0 means the first card in deck
//  -- end, <= (deck_size - 1), (deck_size - 1) means the end card in deck
void Deck::shufflePartial(int start, int end, Random& ran)
{
    assert(end > start);

    if (start >= end)
        return;

    int j;
    char temp;

    int size = deck.size();
    if (end >= size)
        end = size - 1;
    if (start < 0)
        start = 0;

    int passed = start;
    for (int i = start; i < end; i++)
    {
        j = (ran.nextInt() % (end - passed + 1)) + passed;
        temp = deck[j];
        deck[j] = deck[i];
        deck[i] = temp;
        passed++;
    }
}

// copy cards to a hand
void Deck::dealCards(deck_t& cards, int start, int size) const
{
    assert(size <= deck.size());
    if (cards.size() != size)
        cards.resize(size);

    deck_t::const_iterator begin = deck.begin() + start;
    deck_t::const_iterator end   = begin + size;
    cards.assign(begin, end);
}

